package com.party.core.service.wechat.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.party.common.constant.Constant;
import com.party.common.utils.StringUtils;
import com.party.common.utils.wechat.WechatUtils;
import com.party.core.dao.read.wechat.WechatTemplateMassageReadDao;
import com.party.core.dao.read.wechatPlatform.WechatOpenMemberReadDao;
import com.party.core.model.wechat.WechatTemplateMessageWithEvent;
import com.party.core.model.wechatPlatform.WechatOpenMember;
import com.party.core.service.wechat.IWechatDefaultTemplateService;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description: 第三方授权时添加默认的消息模板
 * @Author: yangshoukun
 * @Date: 2018/1/22 17:45
 */
@Service
public class WechatDefaultTemplateService implements IWechatDefaultTemplateService {

    private static Logger logger = LoggerFactory.getLogger(WechatDefaultTemplateService.class);

    @Autowired
    private WechatTemplateMassageService wechatTemplateMassageService;

    @Autowired
    private WechatTemplateMassageReadDao wechatTemplateMassageReadDao;

    @Autowired
    private WechatOpenMemberReadDao wechatOpenMemberReadDao;

    private String message = "";

    @Override
    public String defaultTemplateMessage(List<String> eventNames, String memberId, boolean fromAuthorization) {
        message = "";
        if (CollectionUtils.isEmpty(eventNames) || StringUtils.isEmpty(memberId)) {
            message += "\t事件名称list为空, 或者memberId为空";
            return message;
        }
        Integer deployType = 0;
        if (fromAuthorization) {
            deployType = 0;
        } else {
            deployType = 1;
        }
        // 查询token
        String token = null;
        token = getToken(memberId, deployType);

        if (null == token) {
            message += "\t设置默认消息模板失败";
            return message;
        }
        // 设置行业
        setIndustry(token);
        // 添加模板
        int r = save(eventNames, memberId, token, deployType);
        message += "\t设置默认消息模板成功, 共设置了" + r;
        return message;
    }

    /**
     * 获取商户的token
     * @param memberId
     * @return
     */
    private String getToken(String memberId, Integer deployType) {
        WechatOpenMember wechatOpenMember = wechatOpenMemberReadDao.getByMemberIdAndDeployType(memberId, deployType);
        if (null == wechatOpenMember || StringUtils.isEmpty(wechatOpenMember.getAuthorizerAccessToken())) {
            message += "\t该memberId: " + memberId + " 查询不到对应的token";
            return null;
        }
        return wechatOpenMember.getAuthorizerAccessToken();
    }

    /**
     * 设置行业
     * @param token
     */
    private void setIndustry(String token) {
        String url;
        String param;
        JSONObject jsonObject;
        // 设置行业
        url = WechatTemplateMessageConstant.URL_SET_INDUSTRY.replace(WechatTemplateMessageConstant.ACCESS_TOKEN, token);
        param = WechatTemplateMessageConstant.PARAM_SET_INDUSTRY.replace(WechatTemplateMessageConstant.INDUSTRY_ID_1,
                WechatTemplateMessageConstant.INDUSTRY_ID1).replace(WechatTemplateMessageConstant.INDUSTRY_ID_2,
                WechatTemplateMessageConstant.INDUSTRY_ID2);
        jsonObject = sendPost(url, param);
        if (null == jsonObject) {
            message += "\t设置行业失败";
        }
        if ("43100".equals(jsonObject.get("errcode").toString())) {
            message += "\t更改行业太频繁(一个月只能更改一次)";
        }
    }

    /**
     * 获取消息模板id
     * @param token
     * @param templateIdShort
     * @return
     */
    private String getTemplateId(String token, String templateIdShort) {
        String url;
        String param;
        JSONObject jsonObject;

        // 获得模板id
        url = WechatTemplateMessageConstant.URL_ADD_TEMPLATE.replace(WechatTemplateMessageConstant.ACCESS_TOKEN, token);
        param = WechatTemplateMessageConstant.PARAM_ADD_TEMPLATE.replace(WechatTemplateMessageConstant.TEMPLATE_ID_SHORT,
                templateIdShort);
        jsonObject = sendPost(url, param);
        System.out.println(jsonObject);
        if (null == jsonObject || !"0".equals(jsonObject.get("errcode").toString()) || null == jsonObject.get("template_id")) {
            message += "\t获取消息模板id失败";
            return null;
        }
        return jsonObject.get("template_id").toString();
    }

    /**
     * 获取所有的模板id
     * @param token
     * @return
     */
    private List<String> getAllTemplateIds(String token) {
        String url;
        JSONObject jsonObject;

        // 获取所有的模板
        url = WechatTemplateMessageConstant.URL_GET_ALL_TEMPLATE.replace(WechatTemplateMessageConstant.ACCESS_TOKEN, token);
        jsonObject = WechatUtils.httpRequest(url, WechatUtils.GET, null);
        List<String> ids = new ArrayList<>();
        if (null == jsonObject || null == jsonObject.get("template_list")) {
            message += "\t获取所有模板id失败";
            return ids;
        }
        JSONArray templates = jsonObject.getJSONArray("template_list");
        JSONObject template;
        for (int i = 0, j = templates.size(); i < j; i++) {
            template = templates.getJSONObject(i);
            ids.add(template.getString("template_id"));
        }
        return ids;
    }

    /**
     * 模板消息保存到数据库
     * @param eventNames
     * @param memberId
     * @param token
     * @return
     */
    private int save(List<String> eventNames, String memberId, String token, Integer deployType) {
        // 获取事件名称对应的系统模板相应参数
        List<WechatTemplateMessageWithEvent> templateMessageWithEvents = wechatTemplateMassageReadDao.findByEventName(eventNames,
                Constant.WECHAT_ACCOUNT_TYPE_SYSTEM, null, null);
        int sum = 0;
        List<String> failures = new ArrayList<>();

        List<WechatTemplateMessageWithEvent> temps;
        List<WechatTemplateMessageWithEvent> currentTemplate;
        String templateIdShort;
        String templateId;
        // 获取所有的模板id
        List<String> allCloudIds = getAllTemplateIds(token);
        message += "\n>>>>>>>>>>进入了save, templateMessageWithEvents.size = " + templateMessageWithEvents.size();

        for (WechatTemplateMessageWithEvent entity: templateMessageWithEvents) {
            // 获取模板id
            templateIdShort = TemplateEventName.getTemplateIdShortByEventName(entity.getEventName());
            if (null == templateIdShort) {
                failures.add(entity.getEventName());
                continue;
            }

            WechatOpenMember w = wechatOpenMemberReadDao.getByMemberIdAndDeployType(memberId, deployType);
            String appId = w.getAuthorizerAppid();

            currentTemplate = wechatTemplateMassageReadDao.findByEventName(Arrays.asList(entity.getEventName()),
                    Constant.WECHAT_ACCOUNT_TYPE_PARTNER, null, appId);
            if (CollectionUtils.isEmpty(currentTemplate)) {
                templateId = getTemplateId(token, templateIdShort);
            } else {
                // 如果同行者数据库有该客户的templateId, 则查看客户微信云端的该模板id是否还存在, 存在则直接用, 不存在就新增
                boolean find = false;
                for (String cloudId: allCloudIds) {
                    if (cloudId.equals(currentTemplate.get(0).getTemplateId())) {
                        find = true;
                        break;
                    }
                }
                if (find) {
                    templateId = currentTemplate.get(0).getTemplateId();
                } else {
                    templateId = getTemplateId(token, templateIdShort);
                }
            }

            if (null == templateId) {
                failures.add(entity.getEventName());
                continue;
            }

            entity.setType(Constant.WECHAT_ACCOUNT_TYPE_PARTNER);
            entity.setAppId(appId);
            entity.setTemplateId(templateId);

            temps = wechatTemplateMassageReadDao.withEventList(entity, null, null);
            Date date = new Date();
            if (CollectionUtils.isEmpty(temps)) {
                entity.setId(null);
                entity.setCreateBy(memberId);
                entity.setCreateDate(date);
                entity.setUpdateDate(date);
                wechatTemplateMassageService.insert(entity);
            } else {
                entity = temps.get(0);
                entity.setUpdateBy(memberId);
                entity.setAppId(appId);
                entity.setTemplateId(templateId);
                entity.setUpdateDate(date);
                wechatTemplateMassageService.update(entity);
            }
            sum++;
        }
        if (failures.size() > 0) {
            message += ("\t添加模板失败的事件名称为: " + failures.stream().collect(Collectors.joining(",")));
        }
        return sum;
    }
    /**
     * 向指定 URL 发送POST方法的请求
     *
     * @param url
     *            发送请求的 URL
     * @param param
     *            请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
     * @return 所代表远程资源的响应结果
     */
    public JSONObject sendPost(String url, String param) {
        logger.info("请求路径: {}, 请求参数: {}", url, param);
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
//            conn.setRequestProperty("accept", "*/*");
//            conn.setRequestProperty("connection", "Keep-Alive");
//            conn.setRequestProperty("user-agent",
//                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送 POST 请求出现异常！"+e);
            e.printStackTrace();
        }
        //使用finally块来关闭输出流、输入流
        finally{
            try{
                if(out!=null){
                    out.close();
                }
                if(in!=null){
                    in.close();
                }
            }
            catch(IOException ex){
                ex.printStackTrace();
            }
        }

        JSONObject jsonObject = null;
        if (StringUtils.isNotBlank(result)) {
            jsonObject = JSONObject.parseObject(result);
        }
        logger.info("返回报文: {}", jsonObject);
        return jsonObject;
    }

    /*public static void main(String[] args) {
        System.out.println("=========");
        String token = "6_-6aZ7qyWCurYlIjZ792ca74gKsYC3SpGhhTNpz8Xk9BAd9qiNl92Aah1YKmY4OEq-lPKNIxwEWEDrKxE9AOvbeztEthi" +
                "BZ4CVfya48nrL6dzL2tdIWWSZzPrux57K556ikWA0W3IG1uA0GkyFUYjAGAODH";
        new WechatDefaultTemplateService().getAllTemplateIds(token);
    }*/

    public static class WechatTemplateMessageConstant {
        // 公众号模板消息所属行业编号-主行业: IT科技 互联网/电子商务
        public static final String INDUSTRY_ID1 = "1";
        // 公众号模板消息所属行业编号-主行业: IT科技 IT软件与服务
        public static final String INDUSTRY_ID2 = "2";

        // 设置行业的url
        public static final String URL_SET_INDUSTRY = "https://api.weixin.qq.com/cgi-bin/template/api_set_industry?" +
                "access_token=ACCESS_TOKEN";
        public static final String PARAM_SET_INDUSTRY = "{\"industry_id1\":\"INDUSTRY_ID1\"," +
                "\"industry_id2\":\"INDUSTRY_ID2\"}";
        // 获取模板id的url
        public static final String URL_ADD_TEMPLATE = "https://api.weixin.qq.com/cgi-bin/template/api_add_template?" +
                "access_token=ACCESS_TOKEN";
        public static final String PARAM_ADD_TEMPLATE = "{\"template_id_short\":\"TEMPLATE_ID_SHORT\"}";
        // 获取所有模板列表的url
        public static final String URL_GET_ALL_TEMPLATE = "https://api.weixin.qq.com/cgi-bin/template/get_all_private_template?" +
                "access_token=ACCESS_TOKEN";

        public static final String ACCESS_TOKEN = "ACCESS_TOKEN";

        public static final String INDUSTRY_ID_1 = "INDUSTRY_ID1";

        public static final String INDUSTRY_ID_2 = "INDUSTRY_ID2";

        public static final String TEMPLATE_ID_SHORT = "TEMPLATE_ID_SHORT";

        // 众筹成功的模板编号
        public static final String TEMPLATE_ID_SHORT_SUCCESS = "OPENTM405472520";
        // 众筹收到支持通知的模板编号
        public static final String TEMPLATE_ID_SHORT_SUPPORT = "OPENTM400044406";
        // 评论入选通知(众筹支持收到评论时候的通知)的模板编号
        public static final String TEMPLATE_ID_SHORT_COMMENT = "OPENTM406173715";

    }

    public enum TemplateEventName{
        众筹成功推送(WechatTemplateMessageConstant.TEMPLATE_ID_SHORT_SUCCESS, "众筹成功推送"),
        众筹支持消息推送(WechatTemplateMessageConstant.TEMPLATE_ID_SHORT_SUPPORT,"众筹支持消息推送"),
        收到众筹回复推送(WechatTemplateMessageConstant.TEMPLATE_ID_SHORT_COMMENT,"收到众筹回复推送");

        private String templateIdShort;
        private String eventName;

        private TemplateEventName(String templateIdShort, String eventName) {
            this.eventName = eventName;
            this.templateIdShort = templateIdShort;
        }

        public String getTemplateIdShort() {
            return templateIdShort;
        }

        public void setTemplateIdShort(String templateIdShort) {
            this.templateIdShort = templateIdShort;
        }

        public String getEventName() {
            return eventName;
        }

        public void setEventName(String eventName) {
            this.eventName = eventName;
        }

        public static String getTemplateIdShortByEventName(String eventName) {
            TemplateEventName[] enums = TemplateEventName.values();
            for (TemplateEventName entity: enums) {
                if (entity.getEventName().equals(eventName)) {
                    return entity.getTemplateIdShort();
                }
            }
            return null;
        }
    }
}
